/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package tictactoe;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Random;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;


// ////////////////////////////////////////////////////////////
/**
 *
 * @author houfukude
 */
public class TicTacToeV3 extends JFrame implements ActionListener {

	private static final long serialVersionUID = -2320202799705228234L;

	private JMenuBar menuBar;

	private JMenu menu;

	private JMenuItem menuItem;

	private JButton buttons[] = new JButton[9];

	private int latticeValue[] = { 2, 9, 4, 7, 5, 3, 6, 1, 8 };

	private int pressedValue[] = new int[9]; // 记录1~9的选择顺序

	private int turn = 0, xWins = 0, oWins = 0;

	private CSTree gameTree = new CSTree();

	private String letter, lettetColor;

	public TicTacToeV3() {
		// 设置窗口
		this.setTitle("Tic-Tac-Toe");
		this.setSize(300, 300);
		this.getContentPane().setLayout(new GridLayout(3, 3));
		{// 设置九个格子
			for (int i = 0; i < 9; i++) {
				buttons[i] = new JButton();
				buttons[i].setBackground(Color.WHITE);
				buttons[i].setActionCommand(Integer.toString(latticeValue[i]));// 将点击的格子的值返回
				buttons[i].addActionListener(this);
				getContentPane().add(buttons[i]);
			}
		}

		// 居中显示对话框
		Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
		this.setLocation((int) (screenSize.width - 400) / 2,
				(int) (screenSize.height - 300) / 2);

		// 设置菜单
		menuBar = new JMenuBar();
		setJMenuBar(menuBar);

		menu = new JMenu("游戏");
		menuBar.add(menu);

		menuItem = new JMenuItem("重新开始");
		menuItem.setActionCommand("重新开始");
		menuItem.addActionListener(this);
		menu.add(menuItem);

		menu.addSeparator();

		menuItem = new JMenuItem("人-人");
		menuItem.setActionCommand("人人");
		menuItem.addActionListener(this);
		menu.add(menuItem);

		menuItem = new JMenuItem("人-机");
		menuItem.setActionCommand("人机");
		menuItem.addActionListener(this);
		menu.add(menuItem);

		menuItem = new JMenuItem("机-机");
		menuItem.setActionCommand("机机");
		menuItem.addActionListener(this);
		menu.add(menuItem);

		menu.addSeparator();

		menuItem = new JMenuItem("战况");
		menuItem.setActionCommand("战况");
		menuItem.addActionListener(this);
		menu.add(menuItem);

		menuItem = new JMenuItem("退出");
		menuItem.setActionCommand("退出");
		menuItem.addActionListener(this);
		menu.add(menuItem);

		menu = new JMenu("算法");
		menuBar.add(menu);

		menuItem = new JMenuItem("学习的数据");
		menuItem.setActionCommand("数据");
		menuItem.addActionListener(this);
		menu.add(menuItem);

		menuItem = new JMenuItem("存储数据");
		menuItem.setActionCommand("存储");
		menuItem.addActionListener(this);
		menu.add(menuItem);

	}

	public static void main(String[] args) {
		JFrame starter = new TicTacToeV3();
		starter.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		starter.setVisible(true);
	}

	public void reset() {
		for (int i = 0; i <= 8; i++) {
			buttons[i].setText("");
			buttons[i].setEnabled(true);
			buttons[i].setBackground(Color.WHITE);
			pressedValue[i] = 0;
		}
		turn = 0;
	}

	public void Man2Machine() {

	}

	public void Machine2Machine(int numberOfRound) {

		int randomArray[] = new int[9];
		int temp;
		Random random = new Random();
		for (int i = 0; i < 9; i++) {
			randomArray[i] = i;
		}

		for (int count = 0; count < numberOfRound; count++) {

			reset();
			for (int i = 0; i < 10; i++) {// 生成1-9随机排列数
				int b = Math.abs(random.nextInt() % 9);
				int c = Math.abs(random.nextInt() % 9);
				temp = randomArray[b];
				randomArray[b] = randomArray[c];
				randomArray[c] = temp;
			}

			for (int i = 0; i < 9; i++) {
				if (buttons[randomArray[i]].isEnabled())
					buttons[randomArray[i]].doClick();
				else
					break;
			}

		}

	}

	public void actionPerformed(ActionEvent e) {

		String op = e.getActionCommand();

		if (op.equals("退出"))
			System.exit(0);

		else if (op.equals("重新开始"))
			reset();

		else if (op.equals("数据"))
			gameTree.ShowAllPaths();

		else if (op.equals("存储"))
			gameTree.writeToFile();

		else if (op.equals("机机"))
			Machine2Machine(3);

		else if (op.equals("战况"))
			JOptionPane.showMessageDialog(null, "X赢了" + xWins + "局，O赢了" + oWins
					+ "局！");

		else if (op.length() == 1) {
			/*
			 * op.equals("1")||op.equals("2")||op.equals("3")
			 * ||op.equals("4")||op.equals("5")||op.equals("6")
			 * ||op.equals("7")||op.equals("8")||op.equals("9")
			 */

			if (turn % 2 == 0) {
				letter = "X";// 偶数X
				lettetColor = "blue";
			} else {
				letter = "O";// 奇数O
				lettetColor = "red";
			}

			// 设置按钮文本、使能
			JButton pressedButton = (JButton) e.getSource();
			pressedButton.setText("<HTML><font color=" + lettetColor
					+ " size=10>" + letter + "</font></HTML>");
			pressedButton.setEnabled(false);

			pressedValue[turn] = Integer.parseInt(op);// 取得按下的格子的值

			// 判赢
			if (turn > 3) {
				int i = turn - 2;

				for (; i > 0; i -= 2)
					for (int j = i - 2; j >= 0; j -= 2)
						if (pressedValue[turn] + pressedValue[i]
								+ pressedValue[j] == 15) {

							gameTree.insertPath(pressedValue);

							JOptionPane.showMessageDialog(null, letter + "赢了!");

							if (turn % 2 == 0)
								xWins++;// X赢的次数加1
							else
								oWins++;// O赢的次数加1

							for (i = 0; i <= 8; i++) {
								buttons[i].setEnabled(false);// 赢了后所有按钮都不能用
							}

							i = -1;
							j = -1;// 防止有两条直线成立时对话框出现两次 ，赢的次数也会多记录一次
						}

				if (i <= 0 && i != -3 && turn == 8) {
					JOptionPane.showMessageDialog(null, "平局!");
				}
			}

			turn++;

		}

	}

}
class CSNode {
	private CSNode firstchild;

	private CSNode nextsibling;

	private int value;

	private int depth;

	private int reword;

	public CSNode(int depth, int value, CSNode left, CSNode right) {
		this.depth = depth;
		this.firstchild = left;
		this.nextsibling = right;
		this.value = value;
	}

	public CSNode getFirstchild() {
		return firstchild;
	}

	public CSNode getNextsibling() {
		return nextsibling;
	}

	public int getValue() {
		return value;
	}

	public void setFirstchild(CSNode firstchild) {
		this.firstchild = firstchild;
	}

	public void setNextsibling(CSNode nextsibling) {
		this.nextsibling = nextsibling;
	}

	public void setValue(int value) {
		this.value = value;
	}
}

// /////////////////////////////////////////////////////////////
class CSTree {
	private CSNode root;

	private String treeData;

	public CSTree() {
		root = null;
	}

	public void writeToFile() {
		try {
			FileOutputStream fos = new FileOutputStream("data.txt", false);
			treeData = new String();
			PreOrderTraverse(root);
			for (int i = 0; i < treeData.length(); i++)
				fos.write(treeData.charAt(i));
			fos.write('\n');

			treeData = new String();
			InOrderTraverse(root);
			for (int i = 0; i < treeData.length(); i++)
				fos.write(treeData.charAt(i));

			fos.close();

		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	public void insertPath(int path[]) {
		int i = 0;
		CSNode current, parent, preNode;
		current = preNode = root;
		parent = null;

		while (i < 9 && path[i] != 0) {

			if (current == null) {// 当前指向空
				current = new CSNode(i + 1, path[i], null, null);

				if (root == null)
					root = current;

				else if (parent == preNode)
					parent.setFirstchild(current);
				else
					preNode.setNextsibling(current);

				parent = preNode = current;
				current = parent.getFirstchild();
				i++;
			} else if (current.getValue() == path[i]) {
				preNode = parent = current;
				current = parent.getFirstchild();
				i++;
			}

			else if (current.getValue() != path[i]) {
				preNode = current;
				current = preNode.getNextsibling();
			}
		}
	}

	public void ShowAllPaths() {
		treeData = new String("对策树：\n前序：");
		PreOrderTraverse(root);
		System.out.println(treeData);
		treeData = new String("中序：");
		InOrderTraverse(root);
		System.out.println(treeData);
	}

	private void InOrderTraverse(CSNode node) {
		if (node == null)
			return;
		PreOrderTraverse(node.getFirstchild());// 非叶子结点，遍历第一个孩子
		treeData += node.getValue() + " ";
		PreOrderTraverse(node.getNextsibling());
	}

	/*
	 * public void PreOrderTraverse(CSNode node){ if(node==null) return;
	 *
	 * path[++n]=node.getValue();
	 *
	 * if(node.getFirstchild()==null){//叶子结点 for(int i=0;i<n;i++)
	 * System.out.println(path[i]); n--; }
	 * PreOrderTraverse(node.getFirstchild());//非叶子结点，遍历第一个孩子 n--;
	 * PreOrderTraverse(node.getNextsibling()); n--; }
	 */
	public void PreOrderTraverse(CSNode node) {
		if (node == null)
			return;
		treeData += node.getValue() + " ";
		PreOrderTraverse(node.getFirstchild());// 非叶子结点，遍历第一个孩子
		PreOrderTraverse(node.getNextsibling());
	}
}
